package com.gomoku.botrunning.service.impl.utils;

import lombok.*;


public class Bot {
    @Getter
    Integer userId;
    @Getter
    Integer botId;
    @Getter
    String input;
    @Getter
    String botCode;

    public Bot(Integer userId,Integer botId,String input){
        this.userId = userId;
        this.botId = botId;
        this.input = input;
        if(botId == 1){ //青铜选手
            this.botCode = "package com.gomoku.botrunning.utils;\n" +
                    "\n" +
                    "import com.alibaba.fastjson2.JSON;\n" +
                    "import com.alibaba.fastjson2.JSONObject;\n" +
                    "\n" +
                    "import java.io.File;\n" +
                    "import java.io.FileNotFoundException;\n" +
                    "import java.util.Random;\n" +
                    "import java.util.Scanner;\n" +
                    "\n" +
                    "public class Bot implements java.util.function.Supplier<JSONObject> {\n" +
                    "\n" +
                    "    public JSONObject nextMove(String input) {\n" +
                    "        //input 传入的是一个二维数组标记这黑白棋子的位置\n" +
                    "        int[][] map = JSON.parseObject(input,int[][].class);\n" +
                    "        //默认 1表示黑棋，2表示白棋 最后返回\n" +
                    "        Random random = new Random();\n" +
                    "\n" +
                    "        // 生成1-15之间的随机数（包括1和15）\n" +
                    "        int row = random.nextInt(15) + 1;\n" +
                    "        int col = random.nextInt(15) + 1;\n" +
                    "        while(true){\n" +
                    "            if(map[row][col]!=0){\n" +
                    "                row = random.nextInt(15) + 1;\n" +
                    "                col = random.nextInt(15) + 1;\n" +
                    "            }else\n" +
                    "                break;\n" +
                    "        }\n" +
                    "        System.out.println(\"botmove:row \"+row+\" col\"+col);\n" +
                    "        JSONObject res = new JSONObject();\n" +
                    "        res.put(\"r\",row);\n" +
                    "        res.put(\"c\",col);\n" +
                    "        return res;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public JSONObject get(){\n" +
                    "        File file = new File(\"input.txt\");\n" +
                    "        try {\n" +
                    "            Scanner sc = new Scanner(file);\n" +
                    "            return nextMove(sc.next()); //又封装了一层，从这个文件中得到input\n" +
                    "        } catch (FileNotFoundException e) {\n" +
                    "            throw new RuntimeException(e);\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "}";
        }else if(botId == 2){ //白银选手
            this.botCode = "package com.gomoku.botrunning.utils;\n" +
                    "\n" +
                    "import com.alibaba.fastjson2.JSON;\n" +
                    "import com.alibaba.fastjson2.JSONArray;\n" +
                    "import com.alibaba.fastjson2.JSONObject;\n" +
                    "\n" +
                    "import java.io.File;\n" +
                    "import java.io.FileNotFoundException;\n" +
                    "import java.util.Random;\n" +
                    "import java.util.Scanner;\n" +
                    "\n" +
                    "public class Bot implements java.util.function.Supplier<JSONObject> {\n" +
                    "    private static final int BOARD_SIZE = 16;\n" +
                    "\n" +
                    "    private int[][] parseTo2DArray(JSONArray jsonArray) {\n" +
                    "        int[][] map = new int[BOARD_SIZE][BOARD_SIZE];\n" +
                    "        for (int i = 1; i < BOARD_SIZE; i++) {\n" +
                    "            JSONArray innerArray = jsonArray.getJSONArray(i);\n" +
                    "            for (int j = 1; j < BOARD_SIZE; j++) {\n" +
                    "                map[i][j] = innerArray.getIntValue(j);\n" +
                    "            }\n" +
                    "        }\n" +
                    "        return map;\n" +
                    "    }\n" +
                    "    public JSONObject nextMove(String input) {\n" +
                    "        //input 传入的是一个二维数组标记这黑白棋子的位置\n" +
                    "        JSONArray jsonArray = JSON.parseArray(input);\n" +
                    "        int[][] map = parseTo2DArray(jsonArray);\n" +
                    "        //默认 1表示黑棋，2表示白棋 最后返回\n" +
                    "        Random random = new Random();\n" +
                    "\n" +
                    "        // 生成1-15之间的随机数（包括1和15）\n" +
                    "        int row = random.nextInt(15) + 1;\n" +
                    "        int col = random.nextInt(15) + 1;\n" +
                    "        while (true) {\n" +
                    "            if (map[row][col] != 0) {\n" +
                    "                row = random.nextInt(15) + 1;\n" +
                    "                col = random.nextInt(15) + 1;\n" +
                    "            } else\n" +
                    "                break;\n" +
                    "        }\n" +
                    "        System.out.println(\"botmove:row \" + row + \" col\" + col);\n" +
                    "        JSONObject res = new JSONObject();\n" +
                    "        res.put(\"r\", row);\n" +
                    "        res.put(\"c\", col);\n" +
                    "        return res;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public JSONObject get() {\n" +
                    "        File file = new File(\"input.txt\");\n" +
                    "        try (Scanner sc = new Scanner(file)) {\n" +
                    "            // 修复2：读取全部内容（原 sc.next() 仅读第一个空格前的字符，若JSON带空格会解析失败）\n" +
                    "            StringBuilder inputBuilder = new StringBuilder();\n" +
                    "            while (sc.hasNextLine()) {\n" +
                    "                inputBuilder.append(sc.nextLine().trim());\n" +
                    "            }\n" +
                    "            String input = inputBuilder.toString();\n" +
                    "            return nextMove(input);\n" +
                    "        } catch (FileNotFoundException e) {\n" +
                    "            throw new RuntimeException(\"未找到 input.txt 文件，无法读取棋盘信息\", e);\n" +
                    "        }\n" +
                    "    }\n" +
                    "}";
        } else if (botId ==3) {
            this.botCode="package com.gomoku.botrunning.utils;\n" +
                    "\n" +
                    "import com.alibaba.fastjson2.JSON;\n" +
                    "import com.alibaba.fastjson2.JSONObject;\n" +
                    "\n" +
                    "import java.io.File;\n" +
                    "import java.io.FileNotFoundException;\n" +
                    "import java.util.Random;\n" +
                    "import java.util.Scanner;\n" +
                    "\n" +
                    "public class Bot implements java.util.function.Supplier<JSONObject> {\n" +
                    "    private static final int BOARD_SIZE = 16;\n" +
                    "\n" +
                    "    private JSONObject findDefendMove(int[][] map) {\n" +
                    "        // 检测四个方向：水平、垂直、左上-右下、右上-左下\n" +
                    "        int[][] directions = {{0, 1}, {1, 0}, {1, 1}, {1, -1}};\n" +
                    "\n" +
                    "        for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "            for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                // 跳过非空位（仅检查空位是否能拦截对手）\n" +
                    "                if (map[r][c] != 0) continue;\n" +
                    "\n" +
                    "                // 遍历四个方向，检查该空位是否能拦截对手的连续3子\n" +
                    "                for (int[] dir : directions) {\n" +
                    "                    int dr = dir[0];\n" +
                    "                    int dc = dir[1];\n" +
                    "\n" +
                    "                    // 统计该方向上对手的连续棋子数\n" +
                    "                    int opponentCount = 0;\n" +
                    "                    // 检查“当前空位+方向”的两侧（避免漏判“活三”）\n" +
                    "                    for (int step = -3; step <= 3; step++) {\n" +
                    "                        // 计算当前检查的坐标\n" +
                    "                        int nr = r + step * dr;\n" +
                    "                        int nc = c + step * dc;\n" +
                    "\n" +
                    "                        // 跳过棋盘外的坐标\n" +
                    "                        if (nr < 0 || nr >= BOARD_SIZE || nc < 0 || nc >= BOARD_SIZE) continue;\n" +
                    "\n" +
                    "                        // 遇到对手棋子，计数+1；遇到自身棋子/空位，中断计数\n" +
                    "                        if (map[nr][nc] == 1) {\n" +
                    "                            opponentCount++;\n" +
                    "                        } else if (map[nr][nc] == 2 || (nr == r && nc == c)) {\n" +
                    "                            // 自身棋子或当前空位，不中断（空位是潜在拦截点）\n" +
                    "                            continue;\n" +
                    "                        } else {\n" +
                    "                            break;\n" +
                    "                        }\n" +
                    "                    }\n" +
                    "                    // 若对手有连续3子，当前空位是防守点，直接返回\n" +
                    "                    if (opponentCount >= 3) {\n" +
                    "                        JSONObject defendMove = new JSONObject();\n" +
                    "                        defendMove.put(\"r\", r);\n" +
                    "                        defendMove.put(\"c\", c);\n" +
                    "                        return defendMove;\n" +
                    "                    }\n" +
                    "                }\n" +
                    "            }\n" +
                    "        }\n" +
                    "        // 无防守需求，返回null\n" +
                    "        return null;\n" +
                    "    }\n" +
                    "    public JSONObject nextMove(String input) {\n" +
                    "        //input 传入的是一个二维数组标记这黑白棋子的位置\n" +
                    "        int[][] map = JSON.parseObject(input,int[][].class);\n" +
                    "        //默认 1表示黑棋，2表示白棋 最后返回\n" +
                    "        JSONObject defendMove = findDefendMove(map);\n" +
                    "        if (defendMove == null) {\n" +
                    "            // 如果没有防守位置，创建新的JSONObject\n" +
                    "            defendMove = new JSONObject();\n" +
                    "            Random random = new Random();\n" +
                    "            // 生成1-15之间的随机数（包括1和15）\n" +
                    "            int row = random.nextInt(15) + 1;\n" +
                    "            int col = random.nextInt(15) + 1;\n" +
                    "            while(true) {\n" +
                    "                if (map[row][col] != 0) {\n" +
                    "                    row = random.nextInt(15) + 1;\n" +
                    "                    col = random.nextInt(15) + 1;\n" +
                    "                } else\n" +
                    "                    break;\n" +
                    "            }\n" +
                    "            defendMove.put(\"r\",row);\n" +
                    "            defendMove.put(\"c\",col);\n" +
                    "        }\n" +
                    "        return defendMove;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public JSONObject get(){\n" +
                    "        File file = new File(\"input.txt\");\n" +
                    "        try {\n" +
                    "            Scanner sc = new Scanner(file);\n" +
                    "            return nextMove(sc.next()); //又封装了一层，从这个文件中得到input\n" +
                    "        } catch (FileNotFoundException e) {\n" +
                    "            throw new RuntimeException(e);\n" +
                    "        }\n" +
                    "    }\n" +
                    "}";
        } else if (botId==4) {
            this.botCode="package com.gomoku.botrunning.utils;\n" +
                    "\n" +
                    "import com.alibaba.fastjson2.JSON;\n" +
                    "import com.alibaba.fastjson2.JSONObject;\n" +
                    "import java.io.File;\n" +
                    "import java.io.FileNotFoundException;\n" +
                    "import java.util.*;\n" +
                    "\n" +
                    "public class Bot implements java.util.function.Supplier<JSONObject> {\n" +
                    "    private static final int BOARD_SIZE = 16;\n" +
                    "    private static final int[][] DIRS = {{0, 1}, {1, 0}, {1, 1}, {1, -1}}; // 四个主要方向\n" +
                    "    private static final Random random = new Random();\n" +
                    "\n" +
                    "    // 定义不同棋型的权重分数\n" +
                    "    private static final Map<String, Integer> MOVE_VALUES = new HashMap() {{\n" +
                    "        put(\"FIVE\", 100000);   // 五连必胜\n" +
                    "        put(\"LIVE_FOUR\", 50000); // 活四\n" +
                    "        put(\"DEAD_FOUR\", 1000);  // 眠四\n" +
                    "        put(\"LIVE_THREE\", 3000); // 活三\n" +
                    "        put(\"DEAD_THREE\", 500);  // 眠三\n" +
                    "        put(\"LIVE_TWO\", 200);    // 活二\n" +
                    "        put(\"BLOCK_FIVE\", 80000);// 阻挡对方五连\n" +
                    "        put(\"BLOCK_FOUR\", 40000);// 阻挡对方活四\n" +
                    "        put(\"BLOCK_THREE\", 2000);// 阻挡对方活三\n" +
                    "    }};\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public JSONObject get() {\n" +
                    "        File file = new File(\"input.txt\");\n" +
                    "        try (Scanner sc = new Scanner(file)) {\n" +
                    "            return nextMove(sc.next());\n" +
                    "        } catch (FileNotFoundException e) {\n" +
                    "            throw new RuntimeException(e);\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "    public JSONObject nextMove(String input) {\n" +
                    "        int[][] map = JSON.parseObject(input, int[][].class);\n" +
                    "        JSONObject bestMove = null;\n" +
                    "        int bestScore = Integer.MIN_VALUE;\n" +
                    "\n" +
                    "        // 1. 检查是否可以立即获胜（五连）\n" +
                    "        List<JSONObject> winningMoves = findWinningMoves(map, 2);\n" +
                    "        if (!winningMoves.isEmpty()) {\n" +
                    "            return winningMoves.get(random.nextInt(winningMoves.size()));\n" +
                    "        }\n" +
                    "\n" +
                    "        // 2. 检查是否需要防守对方即将获胜\n" +
                    "        List<JSONObject> blockingMoves = findBlockingMoves(map, 1);\n" +
                    "        if (!blockingMoves.isEmpty()) {\n" +
                    "            return blockingMoves.get(random.nextInt(blockingMoves.size()));\n" +
                    "        }\n" +
                    "\n" +
                    "        // 3. 寻找最佳进攻位置\n" +
                    "        for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "            for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                if (map[r][c] == 0) { // 空位才考虑\n" +
                    "                    int score = evaluatePosition(map, r, c, 2); // 评估白棋在此落子的得分\n" +
                    "                    if (score > bestScore) {\n" +
                    "                        bestScore = score;\n" +
                    "                        bestMove = new JSONObject();\n" +
                    "                        bestMove.put(\"r\", r);\n" +
                    "                        bestMove.put(\"c\", c);\n" +
                    "                    }\n" +
                    "                }\n" +
                    "            }\n" +
                    "        }\n" +
                    "\n" +
                    "        // 4. 如果没有任何理想位置，随机落子\n" +
                    "        if (bestMove == null) {\n" +
                    "            List<JSONObject> emptySpots = new ArrayList<>();\n" +
                    "            for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "                for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                    if (map[r][c] == 0) {\n" +
                    "                        JSONObject res = new JSONObject();\n" +
                    "                        res.put(\"r\",r);\n" +
                    "                        res.put(\"c\",c);\n" +
                    "                        emptySpots.add(res);\n" +
                    "                    }\n" +
                    "                }\n" +
                    "            }\n" +
                    "            if (!emptySpots.isEmpty()) {\n" +
                    "                bestMove = emptySpots.get(random.nextInt(emptySpots.size()));\n" +
                    "            }\n" +
                    "        }\n" +
                    "\n" +
                    "        return bestMove != null ? bestMove : new JSONObject(); // 确保永不返回null\n" +
                    "    }\n" +
                    "\n" +
                    "    // 寻找所有能立即获胜的着法\n" +
                    "    private List<JSONObject> findWinningMoves(int[][] map, int player) {\n" +
                    "        List<JSONObject> moves = new ArrayList<>();\n" +
                    "        for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "            for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                if (map[r][c] == 0) {\n" +
                    "                    int[][] tempMap = deepCopy(map);\n" +
                    "                    tempMap[r][c] = player;\n" +
                    "                    if (checkWin(tempMap, player)) {\n" +
                    "                        JSONObject res = new JSONObject();\n" +
                    "                        res.put(\"r\",r);\n" +
                    "                        res.put(\"c\",c);\n" +
                    "                        moves.add(res);\n" +
                    "                    }\n" +
                    "                }\n" +
                    "            }\n" +
                    "        }\n" +
                    "        return moves;\n" +
                    "    }\n" +
                    "\n" +
                    "    // 寻找必须阻挡的对手着法\n" +
                    "    private List<JSONObject> findBlockingMoves(int[][] map, int opponent) {\n" +
                    "        List<JSONObject> moves = new ArrayList<>();\n" +
                    "        for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "            for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                if (map[r][c] == 0) {\n" +
                    "                    int[][] tempMap = deepCopy(map);\n" +
                    "                    tempMap[r][c] = 2; // 我们在这里落子\n" +
                    "                    if (checkWin(tempMap, opponent)) { // 如果对手在这里会赢\n" +
                    "                        JSONObject res = new JSONObject();\n" +
                    "                        res.put(\"r\",r);\n" +
                    "                        res.put(\"c\",c);\n" +
                    "                        moves.add(res);\n" +
                    "                    }\n" +
                    "                }\n" +
                    "            }\n" +
                    "        }\n" +
                    "        return moves;\n" +
                    "    }\n" +
                    "\n" +
                    "    // 评估指定位置的价值分数\n" +
                    "    private int evaluatePosition(int[][] map, int r, int c, int player) {\n" +
                    "        int score = 0;\n" +
                    "        int[][] tempMap = deepCopy(map);\n" +
                    "        tempMap[r][c] = player; // 模拟落子\n" +
                    "\n" +
                    "        // 计算该位置形成的棋型价值\n" +
                    "        for (int[] dir : DIRS) {\n" +
                    "            String pattern = analyzeLine(tempMap, r, c, dir[0], dir[1], player);\n" +
                    "            score += MOVE_VALUES.getOrDefault(pattern, 0);\n" +
                    "        }\n" +
                    "        return score;\n" +
                    "    }\n" +
                    "\n" +
                    "    // 分析某一行的棋型模式\n" +
                    "    private String analyzeLine(int[][] map, int r, int c, int dr, int dc, int player) {\n" +
                    "        int count = 1; // 当前棋子本身\n" +
                    "        int emptyBefore = 0, emptyAfter = 0;\n" +
                    "\n" +
                    "        // 向前搜索\n" +
                    "        for (int step = 1; ; step++) {\n" +
                    "            int nr = r + dr * step;\n" +
                    "            int nc = c + dc * step;\n" +
                    "            if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE) break;\n" +
                    "            if (map[nr][nc] == player) count++;\n" +
                    "            else if (map[nr][nc] == 0) emptyAfter++;\n" +
                    "            else break; // 遇到对方棋子\n" +
                    "        }\n" +
                    "\n" +
                    "        // 向后搜索\n" +
                    "        for (int step = 1; ; step++) {\n" +
                    "            int nr = r - dr * step;\n" +
                    "            int nc = c - dc * step;\n" +
                    "            if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE) break;\n" +
                    "            if (map[nr][nc] == player) count++;\n" +
                    "            else if (map[nr][nc] == 0) emptyBefore++;\n" +
                    "            else break; // 遇到对方棋子\n" +
                    "        }\n" +
                    "\n" +
                    "        // 根据统计结果判断棋型\n" +
                    "        switch (count) {\n" +
                    "            case 5: return \"FIVE\";\n" +
                    "            case 4:\n" +
                    "                if (emptyBefore + emptyAfter >= 2) return \"LIVE_FOUR\";\n" +
                    "                else return \"DEAD_FOUR\";\n" +
                    "            case 3:\n" +
                    "                if (emptyBefore + emptyAfter >= 2) return \"LIVE_THREE\";\n" +
                    "                else return \"DEAD_THREE\";\n" +
                    "            case 2:\n" +
                    "                if (emptyBefore + emptyAfter >= 2) return \"LIVE_TWO\";\n" +
                    "                break;\n" +
                    "        }\n" +
                    "        return \"NONE\";\n" +
                    "    }\n" +
                    "\n" +
                    "    // 检查是否获胜\n" +
                    "    private boolean checkWin(int[][] map, int player) {\n" +
                    "        for (int r = 1; r < BOARD_SIZE; r++) {\n" +
                    "            for (int c = 1; c < BOARD_SIZE; c++) {\n" +
                    "                if (map[r][c] != player) continue;\n" +
                    "                for (int[] dir : DIRS) {\n" +
                    "                    int count = 1;\n" +
                    "                    for (int step = 1; step < 5; step++) {\n" +
                    "                        int nr = r + dir[0] * step;\n" +
                    "                        int nc = c + dir[1] * step;\n" +
                    "                        if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE || map[nr][nc] != player) break;\n" +
                    "                        count++;\n" +
                    "                    }\n" +
                    "                    if (count >= 5) return true;\n" +
                    "                }\n" +
                    "            }\n" +
                    "        }\n" +
                    "        return false;\n" +
                    "    }\n" +
                    "\n" +
                    "    // 深拷贝二维数组\n" +
                    "    private int[][] deepCopy(int[][] original) {\n" +
                    "        int[][] copy = new int[BOARD_SIZE][BOARD_SIZE];\n" +
                    "        for (int i = 1; i < BOARD_SIZE; i++) {\n" +
                    "            System.arraycopy(original[i], 0, copy[i], 0, BOARD_SIZE);\n" +
                    "        }\n" +
                    "        return copy;\n" +
                    "    }\n" +
                    "}";
        }
    }

}
